import app from '@/main';

interface KeysProperties {
  getters: (key: string) => any,
  state: (key: string) => any,
  commit: (key: string, params?: object) => any,
  dispatch: (key: string, params?: object) => any,
}

/** vuex store 命名提取 */
export class StoreNamespace implements KeysProperties {
  /** 命名空间 */
  namespace: string;
  /** getters */
  getters: (key: string) => any;
  /** state */
  state: (key: string) => any;
  /** 同步函数 */
  commit: (key: string, params?: any) => any;
  /** 异步函数 */
  dispatch: (key: string, params?: any) => Promise<any>;

  /**
   * 执行函数
   *
   * @param method mutations 或者 actions 执行方法
   * @param key 执行方法名
   * @param params 执行参数
   * @deprecated 只能传 object
   */
  syncExecFunction(method: 'dispatch' | 'commit', key: string, params: any[]) {
    if (params.length > 0) {
      let exec = `window.$store.${method}('${this.namespace}/${key}'`;
      for (let param of params) {
        if (param.constructor === {}.constructor) {
          // 如果是对象则将对象转换为 JSON STR
          exec += `, ${JSON.stringify(param)});`
        } else {
          // 否则正常转换即可
          exec += `, ${param})`;
        }
      }
      return new Function(exec)();
    }
  }

  constructor(namespace: string) {
    this.namespace = namespace;
    if (app) {
      let store = app.config.globalProperties.$store;
      (window as any).$store = store;
      this.getters = (key: string) => {
        return store.getters[this.namespace + '/' + key];
      }
      this.state = (key: string) => {
        return store.state[this.namespace][key];
      }
      this.commit = (key: string, params?: any) => {
        // return this.synchExecFunction('commit', key, params);
        return store.commit(this.namespace + '/' + key, params)
      }
      this.dispatch = async (key: string, params?: any) => {
        return await store.dispatch(this.namespace + '/' + key, params);
      }
    } else {
      this.getters = () => {
        // empty function
      };
      this.state = () => {
        // empty function
      };
      this.commit = () => {
        // empty function
      };
      this.dispatch = async () => new Promise((resolve, reject) => {
        reject('app is not found');
      });
    }
  }
}